// @Creation:	30.04.2012
// @Version:	30.04.2012
// 
// @cpu:	x86,
// @author:	alexey kurshakov [alexey.kurshakov@gmail.com]
//
// @Contents:	trace2file.go 
//	Вспомогательные функции для вывод отладочных сообщений в файл
//	Лог-файлы ограничены в размере и автоматически ужимаются архиватором gzip
//
//	BUG: имя у создаваемых лог-файлов не соответствует локальному времени в системе
//	какой-то косяк с пакетом time	
//

package trace

import (
	"compress/gzip"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
	"time"
)

var (
	// Указатель на файл, в который сохраним лог-сообщения
	traceFile *os.File = nil
	// Текущий размер лог-файла
	traceFileSize int = 0
)

// Максимальный размер лог-файла
const maxTraceFileSize int = 1000 * 1024

var LogfileNotOpened error = errors.New("log file not opened")

// Возвращает короткое имя приложения
func getAppName(programPath string) (shortName string) {
	split := strings.Split(strings.Replace(programPath, "/", "\\", -1), "\\")
	shortName = split[len(split)-1]
	return
}

// Сжать файл при помощи gz-архиватора
func compressFileGZ(file string) (err error) {
	// Открываем входной файл для чтения
	ifile, err := os.Open(file)
	if err != nil {
		return err
	}

	// Открываем выходной файл для записи
	ofile, err := os.Create(file + ".gz")
	if err != nil {
		ifile.Close()
		return err
	}
	defer ofile.Close()

	// Создаем экземпляр архиватора
	gzipWriter := gzip.NewWriter(ofile)
	defer gzipWriter.Close()
	io.Copy(gzipWriter, ifile)

	// Удаляем исходный файл
	ifile.Close()
	err = os.Remove(file)
	return
}

// Открыть файл с трассировочными сообщениями 
func traceFileOpen() (err error) {
	// Если указатель не нулевой, то пробуем закрыть файл
	if traceFile != nil {
		err = traceFileClose()
		if err != nil {
			return
		}
	}
	// Определяем текущее время
	// TODO: почему то возвращается не локальное, а глобальное время в системе
	currentTime := time.Now()
	hour, min, sec := currentTime.Clock()
	_, month, day := currentTime.Date()

	// Создаем новый файл
	traceFileSize = 0
	traceFileName := fmt.Sprintf("%s.%02d.%02d.%02d.%02d.%02d.log",
		getAppName(os.Args[0]), int(month), day, hour, min, sec)
	traceFile, err = os.Create(traceFileName)
	return
}

// Сохранить сообщение в файл
func traceFileWrite(traceMsg string) (err error) {
	if traceFile == nil {
		err = LogfileNotOpened
		return
	}
	_, err = traceFile.WriteString(traceMsg + "\n")
	traceFileSize += len(traceMsg)
	if traceFileSize > maxTraceFileSize {
		traceFileClose()
		err = traceFileOpen()
	}
	return
}

// Закрыть файл с трассировочными сообщениями
func traceFileClose() (err error) {
	if traceFile == nil {
		return
	}
	fileName := traceFile.Name()
	err = traceFile.Close()
	if err == nil {
		// архивируем лог-файл           
		go compressFileGZ(fileName)
	}
	return
}
